package cController

import (
	"net/http"
	"reflect"
	"runtime"
	"strings"

	"github.com/gin-gonic/gin"

	"gitee.com/csingo/cLog"
)

type RouteHandlerFunc func() (app string, name string, method string)

func GetGinHandlerFunc(app, name, method string, handler RouteHandlerFunc) (gin.HandlerFunc, error) {
	var result gin.HandlerFunc
	var err error

	if handler != nil {
		app, name, method = handler()
	}

	index := app + "." + name
	instance := container.Get(index)

	if instance == nil {
		cLog.WithContext(nil, map[string]any{
			"source": "cController.GetGinHandlerFunc",
			"app":    app,
			"name":   name,
			"method": method,
		}).Fatalln("获取 controller 异常")
	}

	instanceMethod := reflect.ValueOf(instance).MethodByName(method)
	if !instanceMethod.IsValid() || instanceMethod.IsNil() {
		cLog.WithContext(nil, map[string]any{
			"source": "cController.GetGinHandlerFunc",
			"app":    app,
			"name":   name,
			"method": method,
		}).Fatalln("获取 controller method 异常")
	}

	f := instanceMethod.Interface().(func(*gin.Context) error)

	result = func(ctx *gin.Context) {
		if e := f(ctx); e != nil && !ctx.IsAborted() {
			ctx.AbortWithStatus(http.StatusInternalServerError)
		}
	}

	return result, err
}

func RouteHandler[T ControllerInterface](handler func(T, *gin.Context) error) RouteHandlerFunc {
	methodValue := reflect.ValueOf(handler)
	v := methodValue.Pointer()
	name := runtime.FuncForPC(v).Name()
	parts := strings.Split(name, ".")
	methodPart := parts[len(parts)-1]
	method := strings.TrimSuffix(methodPart, "-fm")
	instance := new(T)
	app, name := (*instance).ControllerName()
	return func() (string, string, string) {
		return app, name, method
	}
}
